服務有一項訂閱功能:每天固定時段,用 LLM 把當天的資料整理成一份易讀的摘要內容,推送給訂戶。這是訂戶最喜歡的功能之一,也是最容易把成本結構做壞的功能。
第一直覺的設計:
for user in subscribers:
content = call_llm(build_personal_prompt(user)) # 每人一次 AI 呼叫
send(user, content)
「每個人拿到客製化內容」聽起來很美好,但把成本攤開算:LLM 呼叫是按 token 計費的,假設一次呼叫成本是 X,訂戶數是 N,這個設計的每日成本是 N·X——你的邊際成本跟訂戶數線性掛鉤。訂閱制的商業模式之所以成立,靠的是「多一個訂戶的邊際成本趨近於零」;每人一次 AI 呼叫直接毀掉這個前提。訂戶成長反而讓毛利惡化,這是商業模式的自殺。
還有第二個問題:速率限制。N 個呼叫擠在同一個排程時窗發出,訂戶一多就會撞上 API 供應商的 rate limit,然後你要開始寫重試、排隊、退避——為一個本來就不該存在的架構擦屁股。
正確的形狀:
def daily_briefing_cycle():
core = call_llm(build_shared_prompt(today_data)) # 全體共用:一次呼叫
for user in subscribers:
content = assemble(core, user.preferences) # 每人差異:純程式組裝
send(user, content)
關鍵的觀察是:訂戶之間真正需要 AI 智慧的部分(理解資料、生成敘述)是共用的;個人化的部分(挑出跟這個使用者相關的段落、按偏好排序)根本不需要 AI,普通程式邏輯就能做。 把兩者拆開,AI 成本從 N·X 變成 X——常數,跟訂戶數無關。多一個訂戶的邊際成本回到趨近於零,商業模式重新成立。
這條原則在專案規範裡的原話是一句鐵律:「一次 AI 呼叫服務所有訂戶」。任何新的 AI 生成功能,設計階段第一個檢查點就是它——不符合這個形狀的設計,要嘛重想,要嘛提出極強的理由(目前為止還沒有出現過夠強的理由)。
誠實地說,有些功能形狀確實無法共用——例如「針對使用者的個人資料組合做 AI 分析」,每個人的輸入根本不同。這類功能的處理方式不是放棄鐵律,是改變計費歸屬:把它做成消耗點數(Day 16)的單次付費功能,讓真正按次發生的成本,由按次付費的收入去覆蓋。
整理成一個對照:
| 功能形狀 | 成本結構 | 商業包裝 |
|---|---|---|
| 輸入全體共用 | 常數 | 訂閱費涵蓋,每日推送 |
| 輸入因人而異 | 按次 | 點數計費,單次兌換 |
成本結構決定商業包裝,而不是反過來。 這句話是整個 AI 功能設計的地基——先搞清楚一個功能的成本是常數還是線性,再決定它該塞進訂閱還是按次收費。順序弄反的下場,是每個月看著帳單想「這功能越受歡迎我越虧」。